﻿using Furion.DistributedIDGenerator;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using net8.Models;
using net8.Models.XiTong;
using net8.Views.XiTong;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;

namespace net8.Controllers.XiTong
{
    /// <summary>
    /// 角色管理
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class XtRoleController : ControllerBase
    {
        [HttpPost]
        public void Save([FromBody] RoleView model)
        {
            DateTime current = DateTime.Now;

            XtRole role = new XtRole()
            {
                Id = model.Id == Guid.Empty ? IDGen.NextID() : model.Id,
                AddTime = current,
                UpdateTime = current,
                IsDel = false,
                RoleName = model.RoleName,
                Remark = model.Remark
            };

            List<XtPermission> list = new List<XtPermission>();
            foreach (Guid item in model.CheckList)
            {
                list.Add(new XtPermission()
                {
                    Id = Guid.NewGuid(),
                    AddTime = current,
                    UpdateTime = current,
                    IsDel = false,
                    IsHalf = false,
                    MenuId = item,
                    RoleId = role.Id
                });
            }
            foreach (Guid item in model.HalfList)
            {
                list.Add(new XtPermission()
                {
                    Id = Guid.NewGuid(),
                    AddTime = current,
                    UpdateTime = current,
                    IsDel = false,
                    IsHalf = true,
                    MenuId = item,
                    RoleId = role.Id
                });
            }

            Save(list, role, (t, s) => t.IsHalf == s.IsHalf && t.MenuId == s.MenuId, p => p.RoleId == role.Id);
        }
        private void Save<T, M>(List<T> list, M role, Expression<Func<T, T, bool>> Propertys, Expression<Func<T, bool>> expression) where T : class, new() where M : class, new()
        {
            List<T> existList = DbHelper.Db.Queryable<T>().Where(expression).ToList();

            var add = list.Except(existList, new ObjectComparer<T>(Propertys)).ToList();
            var del = existList.Except(list, new ObjectComparer<T>(Propertys)).ToList();

            using var tran = DbHelper.Db.UseTran();
            DbHelper.Db.Storageable(role).ExecuteCommand();
            DbHelper.Db.Insertable(add).ExecuteCommand();
            DbHelper.Db.Deleteable(del).ExecuteCommand();
            tran.CommitTran();
        }

        [HttpDelete]
        public void Delete(Guid id)
        {
            DbHelper.Db.Deleteable<XtRole>(id).ExecuteCommand();
        }

        [HttpGet]
        public List<RoleView> GetList()
        {
            List<RoleView> list = DbHelper.Db.Queryable<XtRole>()
                .Includes(r => r.PermissionList)
                .ToList(r => new RoleView()
                {
                    Id = r.Id,
                    RoleName = r.RoleName,
                    Remark = r.Remark,
                    CheckList = r.PermissionList.Where(p => p.IsHalf == false).Select(r => r.MenuId).ToList(),
                    HalfList = r.PermissionList.Where(p => p.IsHalf).Select(r => r.MenuId).ToList()
                });
            return list;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ObjectComparer<T> : IEqualityComparer<T>
    {
        public Expression<Func<T, T, bool>> Propertys { get; set; }
        public ObjectComparer(Expression<Func<T, T, bool>> propertys)
        {
            Propertys = propertys;
        }
        public bool Equals(T? x, T? y)
        {
            if (x is null || y is null) return false;
            var aa = Propertys.Compile()(x, y);
            return aa;
        }

        public int GetHashCode([DisallowNull] T obj)
        {
            return 0;
        }
    }
}
